package com.baizhi.realm;

import com.baizhi.dao.AdminDao;
import com.baizhi.entity.Admin;
import com.baizhi.service.AdminRoleService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Set;

/**
 * 授权的Realm
 */
public class AuthorRealm extends AuthorizingRealm {
    @Autowired
    private AdminDao adminDao;
    @Autowired
    private AdminRoleService roleService;

    /**
     * 获取授权信息
     *
     * principal 身份信息 就是账号的意思
     *
     * 很多的网站 用户名登录 或者 手机号登录 手机号和用户名哪个更重要？手机号更重要 【称之为主身份】
     *
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//        1.获取用户名  getPrimaryPrincipal() 获取主身份 就是获取用户名的意思
        String username = principals.getPrimaryPrincipal().toString();

//        2.根据用户名查询到 角色名字 和 权限字符串
        Set<String> permissions = roleService.getAllPermissionsByUsername(username);
        Set<String> roles = roleService.getAllRolesByUsername(username);

        /**
         * 代码式授权
         * - 按照角色
         * - 按照权限
         */
//        3.封装info返回
        /**
         * 需不需要非null判断？ 不需要
         * 任何一个用户 都一定会有角色 有角色就有权限
         */
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        info.setRoles(roles);
        info.setStringPermissions(permissions);

        return info;
    }

    /**
     * 获取认证信息方法  有了这个授权的Realm 昨天写认证Realm还要吗？
     * 因为授权的Realm功能方法包含了认证信息的获取  认证的Realm就不需要了
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//        1.从token中获取用户名
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
        String username = usernamePasswordToken.getUsername();

//        2.根据用户名查询数据库
        Admin admin = adminDao.selectByName(username);

//        3.如果admin不为null 封装info响应
        if (admin!=null){
            SecurityUtils.getSubject().getSession().setAttribute("admin",admin);
//            获取盐值
            String salt = admin.getSalt();
            ByteSource bytes = ByteSource.Util.bytes(salt);

            return new SimpleAccount(admin.getUsername(),admin.getPassword(),bytes,this.getName());
        }

        return null;
    }
}
